package org.xmx0632.test.jmeter.longtcp.util;

import java.io.UnsupportedEncodingException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class Aes {
	private static byte[] iv;
	private String password;
	private SecretKeySpec key;
	private AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
	private Cipher cipher;

	static {
		initIv();
	}

	public Aes(String accessKey) {
		this.password = accessKey;
		try {
			byte[] keyValue = this.password.getBytes("ASCII");
			this.key = new SecretKeySpec(keyValue, "AES");
			this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void initIv() {
		try {
			iv = "iviviviviviviviv".getBytes("ASCII");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	public String encrypt(String msg) {
		try {
			this.cipher.init(1, this.key, this.paramSpec);

			byte[] encryptData = this.cipher.doFinal(msg.getBytes("UTF-8"));
			return asHex(encryptData);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	public String decrypt(String value) {
		try {
			this.cipher.init(2, this.key, this.paramSpec);
			byte[] bin = asBin(value);
			byte[] decryptData = this.cipher.doFinal(bin);
			return new String(decryptData, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	private static String asHex(byte[] buf) {
		StringBuilder strbuf = new StringBuilder(buf.length * 2);
		for (int i = 0; i < buf.length; i++) {
			if ((buf[i] & 0xFF) < 16) {
				strbuf.append("0");
			}
			strbuf.append(Long.toString(buf[i] & 0xFF, 16));
		}
		return strbuf.toString();
	}

	private static byte[] asBin(String src) {
		if (src.length() < 1) {
			return new byte[0];
		}
		byte[] encrypted = new byte[src.length() / 2];
		for (int i = 0; i < src.length() / 2; i++) {
			int high = Integer.parseInt(src.substring(i * 2, i * 2 + 1), 16);

			int low = Integer.parseInt(src.substring(i * 2 + 1, i * 2 + 2), 16);
			encrypted[i] = ((byte) (high * 16 + low));
		}
		return encrypted;
	}

	public String getEncryptMessageWithAES(String msg, String gatewayId) {
		JSONObject jsonObj = JSON.parseObject(msg);
		jsonObj.put("timestamp", Long.valueOf(System.currentTimeMillis() / 1000L));
//		jsonObj.put("gatewayId", gatewayId);
		// JSONObject gatewayId_obj = jsonObj.getJSONObject("gateway");
		// String gatewayId = gatewayId_obj.getString("gatewayId");

		Map<String, String> gateway = new HashMap<String, String>();
		gateway.put("gatewayId", gatewayId);
		jsonObj.put("gateway", gateway);
		
		String rawData = jsonObj.toJSONString();

//		System.out.println("gatewayId:" + gatewayId + "\nrawData:" + rawData);
		String data = encrypt(rawData);
		

		Map<String, Object> aespack = new HashMap<String, Object>();

		// set different gatewayId
//		Map<String, String> gateway = new HashMap<String, String>();
//		gateway.put("gatewayId", gatewayId);

		aespack.put("gateway", gateway);
		aespack.put("data", data);

		msg = JSON.toJSONString(aespack);
		msg = msg + "\r\n";
//		System.out.println("send msg:\n" + msg);

		return msg;
	}

	public String getDecryptMessageWithAES(String msg) {
		// System.out.println("msg:" + msg);
		JSONObject msgobj = JSON.parseObject(msg);

		String data = msgobj.getString("data");
		// System.out.println("data:" + data);
		return decrypt(data);
	}

}
